#ifndef UNION_DEMO_HPP
#define UNION_DEMO_HPP

#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <utility>

enum class union_body_type {
  text = 1,
  emotion = 2,
};

struct union_demo_body {
  union_demo_body(union_body_type type) : type(type) {}
  union_body_type type;
};

struct union_demo_text : public union_demo_body {
  union_demo_text() : union_demo_body(union_body_type::text), text("test") {}
  std::string text;
};

struct union_demo_emotion : public union_demo_body {
  union_demo_emotion() : union_demo_body(union_body_type::emotion) {}
  int emotion;
};

struct union_demo {
  std::shared_ptr<union_demo_body> body;
};

struct S {
  int mi;
  const std::pair<int, int> &mp; // reference member
};

void union_demo_test() {
  // union_demo o1;
  // o1.type = union_body_type::text;
  // o1.body.text = "haha";
  // union_demo_body body = union_demo_body.emotion;
  // S a{1, {2, 3}};
  union_demo o{std::make_shared<union_demo_text>()};
  if (union_body_type::text == o.body->type) {
    std::shared_ptr<union_demo_text> so_ptr = std::shared_ptr<union_demo_text>(
        o.body, static_cast<union_demo_text *>(o.body.get()));
    std::cout << so_ptr->text << std::endl;
  }

  {
    union_demo o2(o);
  }

  if (union_body_type::text == o.body->type) {
    std::shared_ptr<union_demo_text> so_ptr = std::shared_ptr<union_demo_text>(
        o.body, static_cast<union_demo_text *>(o.body.get()));
    std::cout << so_ptr->text << std::endl;
  }

  std::string test("------");
  std::cout << test << std::endl;
  std::vector<std::string> list;
  list.push_back(std::move(test));
  std::cout << test << std::endl;
}

#endif // UNION_DEMO_HPP